/*
	libsimple_support - a mess of C++ utility code
	https://notabug.org/namark/libsimple_support
	https://gitlab.com/namark/libsimple_support
	https://github.com/namark/libsimple_support

	Copyright (C) 2017-2019 respective authors/contributors

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SIMPLE_SUPPORT_ENUM_FLAGS_OPERATORS_HPP
#define SIMPLE_SUPPORT_ENUM_FLAGS_OPERATORS_HPP

#include <type_traits>

namespace simple::support
{

	template <typename Enum>
	struct define_enum_flags_operators : public std::false_type {};

} // namespace simple::support

#define SIMPLE_SUPPORT_DEFINE_ENUM_FLAGS_OPERATOR(op_sym, underlying_op_sym, return_type) \
template <typename Enum, std::enable_if_t<simple::support::define_enum_flags_operators<Enum>{}>* = nullptr> \
constexpr return_type operator op_sym (const Enum& one, const Enum& other) \
{ \
	using UType = std::underlying_type_t<Enum>; \
	return static_cast<return_type>(static_cast<UType>(one) underlying_op_sym static_cast<UType>(other)); \
}

SIMPLE_SUPPORT_DEFINE_ENUM_FLAGS_OPERATOR(|, |, Enum)
SIMPLE_SUPPORT_DEFINE_ENUM_FLAGS_OPERATOR(&, &, Enum)
SIMPLE_SUPPORT_DEFINE_ENUM_FLAGS_OPERATOR(^, ^, Enum)
SIMPLE_SUPPORT_DEFINE_ENUM_FLAGS_OPERATOR(&&, &, bool)

#undef SIMPLE_SUPPORT_DEFINE_ENUM_FLAGS_OPERATOR

#endif /* end of include guard */
